from flask import Flask, make_response, jsonify, g, current_app as app,Blueprint,request,send_file
from sqlalchemy import select,insert,update,func,join
from sqlalchemy.sql import text
from eim.tools.searchtool import SearchCondition,SearchConditionList,MatchLogic,PartnerRS,GlobalSearch
from eim.tools.dbtool import DBTool
from eim import db,ALLOWED_EXTENSIONS
from eim.result.simple_result import SimpleResult
from eim.Services.docTypeService import DocTypeService
import os
import time

# 创建蓝图
doctypebp=Blueprint("doctypebp","doctypebp",__name__,url_prefix="/doctype")
@doctypebp.route("/newdoctype",methods=["PUT"])
def newdoctype():
    """
    添加新的文件类型
    """
    try:
        param = request.json
        keys = param.keys()
        if 'name' not in keys:
            raise Exception("缺少类别名称")
        if 'code' in keys:
            del(param["code"])
        curpart=time.strftime('%Y%m%d')
        dtool = DBTool(db)
        ncode = dtool.getNewCode(tname='doctype',prechar='ft',datePart=curpart,bitlen=8)
        param["code"]=ncode
        #---------构建父级类别操作类-----------
        dts = DocTypeService(db=db)
        #--------校验父级类别编码是否正确-------
        pcode = param["pcode"]
        if dts.isLeafLevel(pcode):
            return SimpleResult(status='F',msg="父节点必须存在且不能为叶子节点").toDict()
        #--------构建上传路径------------------
        dirname = ""
        levelcnt=0
        if ('pcode' in keys) and (param["pcode"]!=''):
            tmp_pc=param["pcode"]
            chkflag = dts.checkParent(tmp_pc)
            if chkflag:
                dirname,levelcnt = dts.getParentPath(tmp_pc)
            else:
                dirname = './docs/'
        else:
            dirname = './docs/'
        #---将新的类别写入到数据库--   
        param["level"]=levelcnt        
        qry = GlobalSearch(db)
        res=qry.appentData("doctype",param)
        dirname = f"{dirname}{ncode}/"
        os.makedirs(dirname,exist_ok=True)
        return SimpleResult(status='T',value=ncode).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()

#更改文档类别名称
@doctypebp.route("/changeName",methods=['POST'])
def changeName():
    """
    更改文档类别名称
    Returns:
        dict: 返回json结构
    """
    try:
        param = request.json
        if 'dtypename' not in param.keys():
            return SimpleResult(msg='缺少新类别名称').toDict()
        
        if 'dtypecode' not in param.keys():
            return SimpleResult(msg='请指定待修改的文档类别').toDict()
        
        dtypecode = param["dtypecode"]
        
        qry = GlobalSearch(db)
        clist = SearchConditionList()
        cd = SearchCondition('code',MatchLogic.from_Name('EQ'),dtypecode)
        clist.appendCondition(PartnerRS.from_name('AND'),cd)
        vals={
            'name':param["dtypename"]
        }
        res = qry.upgradeData('doctype',vals,clist)
        return SimpleResult(status='T',value=res).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()


@doctypebp.route("/getparent",methods=["GET"])
def getParent():
    try:
        # res = getParentPath('ft2025101000000005')
        dts = DocTypeService(db=db)
        res = dts.getParentPath('sdfsdf')
        return SimpleResult(status='T',value=res).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(es)
        return SimpleResult(msg=info).toDict()
        print(str(es))
        
@doctypebp.route("/typetree",methods=["GET"])
def getDocTypeTree():
    """
    获取文档类别树
    """
    try:
        qry = GlobalSearch(db)
        records = qry.getTableData('doctype',orderfds=['level'],odtype='des')
        docts=DocTypeService(db)
        topnode={
            "text":"根类别",
            "code":"",
            "isleaf":"00",
            "selected":'true',
            "opened":'true',
            "children":[]
        }
        rootchildren = docts.getTypeChildren('',records)
        ts = docts.makeMenuTree(records,topnode)
            
        tl=[ts]
        return SimpleResult(status="T",value=tl).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(info).toDict()

@doctypebp.route("/typesummary/<tcode>/<leafflag>",methods=['GET'])    
def getTypeSummary(tcode:str,leafflag:str):
    """
    获取文档类别的汇总

    Args:
        tcode (str): 类别编号
        leafflag (str): 叶子节点标志
    """
    try:
        res={
            "subtypecnt":0,
            "subfilecnt":0
        }
        qry=GlobalSearch(db)
        sl = SearchConditionList()
        if(tcode=="0"):
            cd=SearchCondition('1',MatchLogic.from_Name('EQ'),val='1')
            sl.appendCondition(PartnerRS.from_name('AND'),cd)
            res["subtypecnt"]=qry.getRecordCnt('doctype',sl)
            return SimpleResult(status='T',value=res).toDict()
        else:
            if(leafflag=='00'):#非叶子节点
                cd=SearchCondition('pcode',MatchLogic.from_Name('EQ'),val=tcode)
                sl.appendCondition(PartnerRS.from_name('AND'),cd)
                res["subtypecnt"]=qry.getRecordCnt('doctype',sl)
            else: #叶子节点
                cd=SearchCondition('type',MatchLogic.from_Name('EQ'),val=tcode)
                sl.appendCondition(PartnerRS.from_name('AND'),cd)
                res["subfilecnt"]=qry.getRecordCnt('docinfo',sl)                 
        return SimpleResult(status='T',value=res).toDict()   
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()
    
    
@doctypebp.route("/deletetype/<pcode>", methods=['DELETE'])
def deleteType(pcode:str):
    """
    删除指定的文档类别
    Args:
        pcode (str): _description_
    """
    try:
        qry=GlobalSearch(db)
        sl=SearchConditionList()
        cd=SearchCondition('code',MatchLogic.from_Name('EQ'),pcode)
        sl.appendCondition(PartnerRS.from_name("AND"),cd)
        res=qry.deleteData('doctype',sl)
        return SimpleResult(status='T',value=res).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(es)
        return SimpleResult(msg=info).toDict()
 
@doctypebp.route("/uploadfile",methods=['POST','GET','OPTIONS'])   
def uploadFile():
    """
    上传文件
    """
    qry=GlobalSearch(db)
    try:
        fs=request.files["file"];
        
        curpart=time.strftime('%Y%m%d')
        dts = DocTypeService(db=db)
        pp,level=dts.getParentPath(request.form['pcode'])
        dirpath=f"{pp}{fs.filename}"
        dbtool = DBTool(db)
        info={
            "code":dbtool.getNewCode('docinfo','f',curpart,6),
            "name":fs.filename,
            "type":request.form["pcode"],
            "size":request.form['fsize'],
            "upuser":request.form["username"],
            "uptime":time.strftime("%Y-%m-%d %H:%M:%S"),
            "comment":request.form["filecomment"],
            "ver":request.form["ver"],
            "dpos":dirpath
        }
       
        trans = qry.beginTrans()
        fs.save(dirpath)
        qry.appentData('docinfo',info)
        qry.commit()
        return SimpleResult(status='T',value="").toDict()
    except Exception as es:
        qry.rollback()
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()
    
@doctypebp.route("/pageinfo/<int:pn>/<int:ps>",methods=["POST"])
def pageDocinfo(pn,ps):
    """
    分页获取文档列表

    Args:
        pn (_type_): 页码
        ps (_type_): 页面尺寸
    """
    try:
        if pn<1:
            pn=1
        if ps<50:
            ps=50
        param = request.json
        qry = GlobalSearch(db)
        sl = SearchConditionList()
        for item in param["pms"]:
            cd = SearchCondition(item["CD"]["field"],MatchLogic.from_Name(item["CD"]["logic"]),item["CD"]["value"])
            sl.appendCondition(PartnerRS.from_name(item["RS"]),cd)
        res = qry.pageTableInfo(pn,ps,'docinfo',param["cols"],sl)
        return SimpleResult(status='T',value=res).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()
    

@doctypebp.route("/filedownload/<fcode>",methods=["GET"])
def fileDownLoad(fcode:str):
    """
    文件下载

    Args:
        fcode (str): 文件编码
    """
    try:
        qry = GlobalSearch(db)
        sl = SearchConditionList()
        cd = SearchCondition("code",MatchLogic.from_Name('EQ'),fcode)
        sl.appendCondition(PartnerRS.from_name('AND'),cd)
        dpos = qry.getTableScalar('docinfo',['dpos'],sl)
        fullpath = os.path.abspath(dpos)
        return send_file(fullpath,as_attachment=True,mimetype="application/octet-stream")
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()
    
@doctypebp.route("/getleaftype",methods=['GET'])
def getleaftype():
    """
    获取叶子节点类
    """
    try:
        qry = GlobalSearch(db)
        sl = SearchConditionList()
        cd = SearchCondition('isleaf',MatchLogic.from_Name('EQ'),'01')
        sl.appendCondition(PartnerRS.from_name('AND'),cd)
        res = qry.getTableData('doctype',['code','name'],sl)
        leaftree={}
        for item in res:
            leaftree[item["code"]]=item["name"]
            
        return SimpleResult(status='T',value=leaftree).toDict()
    except Exception as es:
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()
    
@doctypebp.route("/deltypefile/<fcode>",methods=["DELETE"])
def deleteTypeFile(fcode:str):
    """
    根据文件编号删除文件

    Args:
        fcode (str): 待删除的文件编号
    """
    qry = GlobalSearch(db)
    try:
        sl = SearchConditionList()
        cd = SearchCondition("code",MatchLogic.from_Name('EQ'),fcode)
        sl.appendCondition(PartnerRS.from_name('AND'),cd)
        dpos = qry.getTableScalar('docinfo',['dpos'],sl)
        fullpath = os.path.abspath(dpos)
        
        qry.beginTrans()
        os.remove(fullpath)
        qry.deleteData('docinfo',sl)
        qry.commit()
        return SimpleResult(status="T",value=fcode).toDict()
    except Exception as es:
        qry.rollback()
        info = str(es)
        app.logger.error(info)
        return SimpleResult(msg=info).toDict()